package com.exam.api.modules.system.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.ObjUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.exam.api.common.Const;
import com.exam.api.modules.system.domain.TblMenu;
import com.exam.api.modules.system.dto.MenuAddDTO;
import com.exam.api.modules.system.dto.MenuIdDTO;
import com.exam.api.modules.system.dto.MenuQueryDTO;
import com.exam.api.modules.system.dto.MenuUpdateDTO;
import com.exam.api.modules.system.event.MenuDeleteEvent;
import com.exam.api.modules.system.mapper.TblMenuMapper;
import com.exam.api.modules.system.service.TblMenuService;
import jakarta.annotation.Resource;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.util.List;

/**
 * 菜单逻辑接口类实现类
 *
 * @author bcheng
 */
@Service
public class TblMenuServiceImpl extends ServiceImpl<TblMenuMapper, TblMenu> implements TblMenuService {

    @Resource
    private ApplicationContext applicationContext;


    @Override
    public List<String> listManagerPermissionCodes() {
        long userId = StpUtil.getLoginIdAsLong();
        return listPermissionCodes(userId);
    }

    @Override
    public List<Tree<Long>> listManagerMenuTree(@Validated MenuQueryDTO dto) {
        long userId = StpUtil.getLoginIdAsLong();
        List<TblMenu> menus = baseMapper.listUserMenus(userId);
        //配置
        TreeNodeConfig config = new TreeNodeConfig();
        config.setIdKey("menuId");
        config.setParentIdKey("parentMenuId");
        config.setWeightKey("sort");
        //最大递归深度
        config.setDeep(5);
        Long rootId = 0L;
        if (!ObjUtil.isNull(dto.getParentMenuId())) {
            rootId = dto.getParentMenuId();
        }
        return TreeUtil.build(menus, rootId, config, (node, tree) -> {
            tree.setId(node.getMenuId());
            tree.setParentId(node.getParentMenuId());
            tree.setWeight(node.getSort());
            tree.setName(node.getName());
            tree.putExtra("other", node);
        });
    }


    @Override
    public List<String> listPermissionCodes(Long userId) {
        return baseMapper.listPermissionCodes(userId);
    }

    @Override
    public List<Tree<Long>> treeMenu(MenuQueryDTO dto) {
        List<TblMenu> list = lambdaQuery()
                .eq(TblMenu::getIsDelete, Const.ZERO)
                .orderByDesc(TblMenu::getSort)
                .list();
        //配置
        TreeNodeConfig config = new TreeNodeConfig();
        config.setIdKey("menuId");
        config.setParentIdKey("parentMenuId");
        config.setWeightKey("sort");
        Long rootId = 0L;
        if (!ObjUtil.isNull(dto.getParentMenuId())) {
            rootId = dto.getParentMenuId();
        }
        return TreeUtil.build(list, rootId, config, (node, tree) -> {
            tree.setId(node.getMenuId());
            tree.setParentId(node.getParentMenuId());
            tree.setWeight(node.getSort());
            tree.setName(node.getName());
            tree.putExtra("other", node);
        });
    }

    @Override
    public TblMenu getMenu(MenuIdDTO dto) {
        return getById(dto.getMenuId());
    }

    @Override
    public void addMenu(MenuAddDTO dto) {
        save(dto.converter());
    }

    @Override
    public void updateMenu(MenuUpdateDTO dto) {
        updateById(dto.converter());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteMenu(MenuIdDTO dto) {
        removeById(dto.getMenuId());
        //发送删除菜单事件
        applicationContext.publishEvent(new MenuDeleteEvent(dto.getMenuId()));
    }
}
